home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / zmdm.zoo / expandar.c < prev    next >
C/C++ Source or Header  |  1991-04-27  |  15KB  |  734 lines

  1.  
  2.     /* 
  3.      *     Examine each argument given to expandargs()
  4.      *     If it is a directory, then expand it
  5.      *    to all its component files, recursively
  6.      *    till you bottom out.
  7.      *    If it is not a directory, then just pass it on.
  8.      *
  9.      *    Inputs: routine, argc, argv
  10.      *    Outputs: nargc, nargv (calls routine(nargc, nargv))
  11.      *    To test: compile with -DTEST
  12.      *         define MWC if using Mark Williams C
  13.      *         run with a directory as an arg
  14.      *    Author: JRB    bammi@mandrill.ces.CWRU.edu
  15.      *    Requirements: Mark Williams C or Alcyon C
  16.      *        Wants lots of Dynamic memory. It
  17.      *        all depends upon how many files you
  18.      *        have. Use the -P option to prune
  19.      *        out subdirectories and do things
  20.      *        one at a time, if you keep running
  21.      *        out of memory.
  22.      *        With Mark Williams i use _stksize = 128K
  23.      *        With Alcyon i use memory model 2 (half of
  24.      *        of avail memory) in GEMSTART.S
  25.      *
  26.          *      WARNINGS: Be CAREFUL about the 40 folder bug. Use
  27.      *              GEMBOOT or FOLDRXXX when dealing with
  28.      *          a deeply nested file structure.
  29.      *
  30.      *    Added -P name prune option at the suggestion of dietz@zhmti
  31.      *    Multiple -P's may be given on the command line.
  32.      *    -P name may be given anywhere on the command line. -P name
  33.      *    will prune the subdirectories named as arguement to -P.
  34.      *    ie: when the program is decending the file hierarchy it
  35.      *    will not visit the pruned branches.
  36.      *     NOTE that the option is -P and not -p
  37.      *          (-p is a valid sz option).
  38.      *    NOTE that the arguement given to -P can be the name
  39.      *     of a file or a directory. In case it is a file,
  40.      *    that file is skipped.
  41.      *
  42.      */
  43.  
  44. /*
  45.  * Expand argc, so that the called routine(nargc,nargv) receives only
  46.  * filenames, in nargv[][]
  47.  *
  48.  ************************************************************************
  49.  *                                    *
  50.  *      WARNING:  Be CAREFUL about the 40 folder bug. Use        *
  51.  *              GEMBOOT or FOLDRXXX when dealing with            *
  52.  *          a deeply nested file structure.            *
  53.  *                                    *
  54.  ************************************************************************
  55.  *
  56.  *    Jwahar Bammi
  57.  *     bang:   {any internet host}!dsrgsun.ces.CWRU.edu!bammi
  58.  *     domain: bammi@dsrgsun.ces.CWRU.edu
  59.  *    GEnie:    J.Bammi
  60.  */
  61.  
  62. #ifdef TEST
  63. #include <stdio.h>
  64. #include <osbind.h>
  65. #include <ctype.h>
  66. #endif
  67.  
  68. #ifdef TRUE
  69. #undef TRUE
  70. #endif
  71. #ifdef OK
  72. #undef OK
  73. #endif
  74. #ifdef FALSE
  75. #undef FALSE
  76. #endif
  77.  
  78. #define TRUE     1
  79. #define OK     0
  80. #define FALSE     0
  81. #define Realloc     realloc
  82.  
  83. #ifdef TEST
  84. struct    stat
  85. {
  86.     char    st_sp1[21];    /* Junk        */
  87.     char    st_mode;       /* File attributes */
  88.     int    st_time;       /* Mod Time      */
  89.     int     st_date;       /* Mod date      */
  90.     long    st_size;       /* File size       */
  91.     char    st_name[14];   /* File name       */
  92. };
  93. #endif
  94.  
  95. typedef struct _prunelist {
  96.     char *name;            /* name of subdirectory to prune */
  97.     struct _prunelist *next;    /* ptr to next */
  98. } PRUNELIST;
  99.  
  100. static char *ProgName;
  101. static PRUNELIST *PruneList = (PRUNELIST *)NULL; /* Head of PruneList */
  102.  
  103. #if defined(__STDC__) || defined(__cplusplus)
  104. # define P_(s) s
  105. #else
  106. # define P_(s) ()
  107. #endif
  108.  
  109. static char **CopyToNargv P_((char *string, int nargc, char **nargv));
  110. static char **ExpandStack P_((char **Stack));
  111. static void FreeStack P_((void));
  112. static void FreeNargv P_((int nargc, char *nargv[]));
  113. static void FreePrune P_((void));
  114. static void FreeUp P_((int nargc, char **nargv));
  115. static int PushDir P_((char *name));
  116. static char *PopDir P_((void));
  117. static int ProcessDirs P_((int *nargc, char ***nargv));
  118. static PRUNELIST *AddPrune P_((PRUNELIST *list, char *name));
  119. static int OnPruneList P_((PRUNELIST *list, char *name));
  120. static int isdir P_((char *name, int attr));
  121. char *alltolower P_((char *s));
  122.  
  123. #undef P_
  124.  
  125. extern int existd();
  126.  
  127. expandargs(routine, argc, argv)
  128. int (*routine)();
  129. int argc;
  130. char **argv;
  131. {
  132.     register int status;
  133.     int nargc;
  134.     char **nargv;
  135.     extern char **CopyToNargv();
  136.     extern PRUNELIST *AddPrune();
  137.     extern int existd();
  138.  
  139.     nargc = 0;
  140.     nargv = (char **)NULL;
  141.     ProgName = *argv;
  142.     
  143.     /* copy argv[0] blindly */
  144.     if((nargv = CopyToNargv(*argv, nargc, nargv)) == (char **)NULL)
  145.     {
  146.         FreeUp(nargc, nargv);
  147.         return(~OK);
  148.     }
  149.  
  150.     nargc++;
  151.     
  152.     while((--argc) > 0)
  153.     {
  154.         argv++;
  155.         if(**argv == '-')
  156.         {
  157.             /* copy any options except -P */
  158. #ifdef TEST
  159.             /* some shell pass -P as -p */
  160.             if( ((*argv)[1] == 'P') || ((*argv)[1] == 'p'))
  161. #else
  162.             if( (*argv)[1] == 'P')
  163. #endif
  164.             {
  165.                 if((--argc) <= 0)
  166.                 {
  167.                     fprintf(STDERR,"no argument given to -P\n");
  168.                     FreeUp(nargc, nargv);
  169.                     return(~OK);
  170.                 }
  171.                 if((PruneList = AddPrune(PruneList,*++argv))
  172.                    == (PRUNELIST *)NULL)
  173.                 {
  174.                     FreeUp(nargc, nargv);
  175.                     return(~OK);
  176.                 }
  177.             }
  178.             else
  179.             {
  180.                 if((nargv = CopyToNargv(*argv, nargc, nargv))
  181.                    == (char **)NULL)
  182.                 {
  183.                     FreeUp(nargc, nargv);
  184.                     return(~OK);
  185.                 }
  186.                 else
  187.                     nargc++;
  188.             }
  189.             
  190.         }
  191.         else
  192.         {
  193.             /* If its not on the PruneList then */
  194.             if(!OnPruneList(PruneList, *argv))
  195.             {
  196.                 /* if it is a directory, push it */
  197.                 if(existd(*argv))
  198.                 {
  199.                     if((status = PushDir(*argv)) != OK)
  200.                     {
  201.                         FreeUp(nargc, nargv);
  202.                         return(status);
  203.                     }
  204.                 }
  205.                 else
  206.                 {
  207.                     /* it is NOT a directory, copy to nargv */
  208.                     if((nargv = CopyToNargv(*argv, nargc, nargv))
  209.                        == (char **)NULL)
  210.                     {
  211.                         FreeUp(nargc, nargv);
  212.                         return(~OK);
  213.                     }
  214.                     else
  215.                         nargc++;
  216.                 }
  217.             }
  218.         }
  219.     } /* while */
  220.  
  221.     /* process pushed directories if any */
  222.     if((status = ProcessDirs(&nargc, &nargv)) != OK)
  223.     {
  224.         FreeUp(nargc, nargv);
  225.         return(status);
  226.     }
  227.     /* else Free the Stack and Prune List, call *routine */
  228.     FreeStack();
  229.     FreePrune();
  230.     status =  (*routine)(nargc, nargv);
  231.     FreeNargv(nargc, nargv);
  232.  
  233.     return status;
  234.  
  235. }
  236.  
  237. /*
  238.  * Expand nargv by an element and copy a String into the new element
  239.  *
  240.  */
  241. static char **CopyToNargv(string, nargc, nargv)
  242. char *string;
  243. int nargc;
  244. char **nargv;
  245. {
  246. #ifdef __GNUC__
  247.     extern void *malloc(size_t), *Realloc(void *, size_t);
  248. #else
  249.     extern char *malloc(), *Realloc();
  250. #endif
  251.     extern char  *strcpy();
  252. #ifdef __GNUC__
  253.     extern size_t strlen();
  254. #else
  255.     extern int strlen();
  256. #endif
  257.     
  258.     /* expand nargv by 1 element */
  259.     if(nargv == (char **)NULL)
  260.         /* do it with malloc for the first one */
  261.         nargv = (char **)malloc(sizeof(char **));
  262.     else
  263.         /* do it with Realloc for others */
  264.         nargv = (char **)Realloc(nargv, (nargc+1)*sizeof(char **));
  265.     
  266.     if(nargv == (char **)NULL)
  267.     {
  268.         /* failed to get memory */
  269.         fprintf(STDERR,"%s(CopyToNargv()): Out of Memory\n", ProgName);
  270.         return ((char **)NULL);
  271.     }
  272.  
  273.     /* Get mem for string */
  274.     if(( nargv[nargc] = malloc(strlen(string)+1)) == (char *)NULL)
  275.     {
  276.         /* failed to get memory */
  277.         fprintf(STDERR,"%s(CopyToNargv()): Out of Memory\n", ProgName);
  278.         return ((char **)NULL);
  279.     }
  280.  
  281.     /* copy string into nargv[nargc] */
  282.     (void)strcpy( nargv[nargc], string);
  283.     return(nargv);
  284. }
  285.  
  286. static char **Stack = (char **)NULL;    /* directory stack */
  287. static char StackSize = 0;        /* Size of current Stack */
  288. static int    Top   = -1;
  289. #define STACK_EMPTY    (Top < 0)
  290. #define CHUNKSIZE    16
  291.  
  292. /*
  293.  * Grow the Stack by one chunk of CHUNKSIZE elements
  294.  *
  295.  */
  296. static char **ExpandStack(Stack)
  297. char **Stack;
  298. {
  299. #ifdef __GNUC__
  300.     extern void *malloc(size_t), *Realloc(void *, size_t);
  301. #else
  302.     extern char *malloc(), *Realloc();
  303. #endif
  304.     
  305.     /* Grow Stack */
  306.     if(Stack == (char **)NULL)
  307.         /* with malloc */
  308.         Stack = (char **)malloc(CHUNKSIZE * sizeof(char **));
  309.     else
  310.         /* with Realloc */
  311.         Stack = (char **)Realloc(Stack, (StackSize+CHUNKSIZE) *
  312.                              sizeof(char **));
  313.  
  314.     if(Stack == (char **)NULL)
  315.     {
  316.         /* outa mem */
  317.         fprintf(STDERR,"%s(ExpandStack()): Out of Memory\n", ProgName);
  318.         return((char **)NULL);
  319.     }
  320.     StackSize += CHUNKSIZE;
  321.     return(Stack);
  322. }
  323.  
  324. /*
  325.  * Free the Stack
  326.  *
  327.  */
  328. static void FreeStack()
  329. {
  330.     if(StackSize > 0)
  331.         (void)free(Stack);
  332.     Stack = (char **)NULL;
  333.     StackSize = 0;
  334.     Top   = -1;
  335. }
  336.  
  337. /*
  338.  * Free Nargv
  339.  *
  340.  */
  341. static void FreeNargv(nargc, nargv)
  342. int nargc;
  343. char *nargv[];
  344. {
  345.     register int i;
  346.  
  347.     for(i = 0; i < nargc; i++)
  348.         (void)free(nargv[i]);
  349.     if(nargc > 0)
  350.         (void)free(nargv);
  351. }
  352.  
  353. /*
  354.  * Free the PruneList
  355.  *
  356.  */
  357. static void FreePrune()
  358. {
  359.     register PRUNELIST *p, *next;
  360.  
  361.     for(p = PruneList; p != (PRUNELIST *)NULL; p = next)
  362.     {
  363.         next = p->next;
  364.         (void)free(p);
  365.     }
  366.     PruneList = (PRUNELIST *)NULL;